#include"IR.h"
#include"semantic.h"
using namespace std;
IR* oneIR = new IR();

opn::opn(){

}


opn::opn(int val):type(OPN_INT),constInt(val){

}

opn::opn(float val):type(OPN_FLOAT),constFloat(val){

}

opn::opn(codenode** val):type(OPN_SYM),cn(val){

}

opn::opn(int type,int no):type(type),constInt(no){

}

string opn::toString(){
  switch(type){
    case  OPN_INT       :return to_string(constInt);                                 break;
    case  OPN_FLOAT     :return to_string(constFloat);                               break;
    case  OPN_SYM       :return (*cn)->result->toString();                           break;
    case  OPN_TEMP      :return "temp"+to_string(constInt);                          break;
    case  OPN_LABEL     :return "label"+to_string(constInt);                         break;
    default             :return "$$";
  }
  return "$$";
}

codenode::codenode(int op):op(op),opn1(NULL),opn2(NULL),result(NULL),lval(0),cond(0){
  if(op!=OP_NULL&&op!=OP_ARRAY)index = IR::index++;
}

codenode::codenode(int op,sym *result):op(op),opn1(NULL),opn2(NULL),result(result),lval(0),cond(0){
  if(op!=OP_NULL&&op!=OP_ARRAY)index = IR::index++;
}

codenode::codenode(int op,sym* opn1,sym *result):op(op),opn1(opn1),opn2(NULL),result(result),lval(0),cond(0){
  if(op!=OP_NULL&&op!=OP_ARRAY)index = IR::index++;
  if(op==OP_CALL)valid = 0;
}

codenode::codenode(int op,sym *opn1,sym *opn2,sym *result):op(op),opn1(opn1),opn2(opn2),result(result),lval(0),cond(0){
  if(op!=OP_NULL&&op!=OP_ARRAY)index = IR::index++;
}

void codenode::setValid(){
  valid = 1;
  if(op == OP_ARRAY){
    index = IR::index++;
    oneIR->push(this);
  }
}

void codenode::setLval(){
  lval = 1;
  if(op==OP_ARRAY)
    index = IR::index++;
}

codenode* codenode::setCond(sym* label){
  cond = 1;
  valid = 1;
  result = label;
  if(op == OP_ADD      ||
     op == OP_MINUS    ||
     op == OP_MUL      ||
     op == OP_DIV      ||
     op == OP_MOD      ||
     op == OP_NEGATIVE ||
     op == OP_CALL       ){
    codenode* cn = new codenode(OP_NOTEQUAL,result,new opn(0),NULL);
    cn->setCond(label);
    oneIR->push(cn);
    return cn;
  }
  return NULL;
}

void codenode::display(){
  printf("%d ",index);
  switch(op){
    case OP_FUNCTION    :printf("FUNCTION %s\n",result->toString().c_str());                                break;
    case OP_PARAM       :printf("PARAM %s\n",   result->toString().c_str());                                break;
    case OP_GOTO        :printf("GOTO %s\n",    result->toString().c_str());                                break;
    case OP_ARG         :printf("ARG %s\n",     result->toString().c_str());                                break;
    case OP_LABEL       :printf("LABEL %s\n",   result->toString().c_str());                                break;
    case OP_CALL        :if(valid)
                           printf("%s = CALL %s\n",result->toString().c_str(),
                                                 opn1->toString().c_str());
                         else
                           printf("CALL %s\n",opn1->toString().c_str());                                    break;
    case OP_RETURN      :if(result!=NULL)
                           printf("RETURN %s\n",result->toString().c_str());
                         else
                           printf("RETURN\n");                                                              break;
    case OP_ASSIGN      :printf("%s = %s\n",result->toString().c_str(),
                                                 opn1->toString().c_str());                                 break;
    case OP_ARRAY       :if(lval)
                           printf("%s[%s] = %s\n",opn1->toString().c_str(),opn2->toString().c_str(),
                                                 result->toString().c_str()); 
                         else
                           printf("%s = %s[%s]\n",result->toString().c_str(),
                                                 opn1->toString().c_str(),opn2->toString().c_str());        break;
    case OP_ADD         :printf("%s = %s + %s\n",result->toString().c_str(),
                                                 opn1->toString().c_str(),opn2->toString().c_str());        break;
    case OP_MINUS       :printf("%s = %s - %s\n",result->toString().c_str(),
                                                 opn1->toString().c_str(),opn2->toString().c_str());        break;
    case OP_MUL         :printf("%s = %s * %s\n",result->toString().c_str(),
                                                 opn1->toString().c_str(),opn2->toString().c_str());        break;
    case OP_DIV         :printf("%s = %s / %s\n",result->toString().c_str(),
                                                 opn1->toString().c_str(),opn2->toString().c_str());        break;
    case OP_MOD         :printf("%s = %s %% %s\n",result->toString().c_str(),
                                                 opn1->toString().c_str(),opn2->toString().c_str());        break;
    case OP_NOT         :if(cond)
                           printf("IF %s == 0 GOTO %s\n",result->toString().c_str(),
                                                 opn1->toString().c_str());
                         else
                           printf("%s = !%s\n",result->toString().c_str(),
                                                 opn1->toString().c_str());                                 break;
    case OP_NEGATIVE    :printf("%s = -%s\n",result->toString().c_str(),
                                                 opn1->toString().c_str());                                 break;
    case OP_AND         :                                                                                   break;
    case OP_OR          :                                                                                   break;
    case OP_EQUAL       :if(cond)
                           printf("IF %s == %s GOTO %s\n",opn1->toString().c_str(),opn2->toString().c_str(),
                                                 result->toString().c_str());
                         else
                           printf("%s = %s == %s\n",result->toString().c_str(),
                                                 opn1->toString().c_str(),opn2->toString().c_str());        break;
    case OP_NOTEQUAL    :if(cond)
                           printf("IF %s != %s GOTO %s\n",opn1->toString().c_str(),opn2->toString().c_str(),
                                                 result->toString().c_str());
                         else
                           printf("%s = %s != %s\n",result->toString().c_str(),
                                                 opn1->toString().c_str(),opn2->toString().c_str());        break;
    case OP_GRATER      :if(cond)
                           printf("IF %s > %s GOTO %s\n",opn1->toString().c_str(),opn2->toString().c_str(),
                                                 result->toString().c_str());
                         else
                           printf("%s = %s > %s\n",result->toString().c_str(),
                                                 opn1->toString().c_str(),opn2->toString().c_str());        break;
    case OP_LESS        :if(cond)
                           printf("IF %s < %s GOTO %s\n",opn1->toString().c_str(),opn2->toString().c_str(),
                                                 result->toString().c_str());
                         else
                           printf("%s = %s < %s\n",result->toString().c_str(),
                                                 opn1->toString().c_str(),opn2->toString().c_str());        break;
    case OP_NOTGRATER   :if(cond)
                           printf("IF %s <= %s GOTO %s\n",opn1->toString().c_str(),opn2->toString().c_str(),
                                                 result->toString().c_str());
                         else
                           printf("%s = %s <= %s\n",result->toString().c_str(),
                                                 opn1->toString().c_str(),opn2->toString().c_str());        break;
    case OP_NOTLESS     :if(cond)
                           printf("IF %s >= %s GOTO %s\n",opn1->toString().c_str(),opn2->toString().c_str(),
                                                 result->toString().c_str());
                         else
                           printf("%s = %s >= %s\n",result->toString().c_str(),
                                                 opn1->toString().c_str(),opn2->toString().c_str());        break;
    default             :printf("$$$\n");
  }
}

int IR::labelno = 0;
int IR::index   = 0;

opn* IR::genLabel(){
  return new opn(OPN_LABEL,++IR::labelno);
}

opn* IR::genTemp(){
  return new opn(OPN_TEMP,++IR::labelno);
}

void IR::push(codenode* n){
  codes.push_back(n);
}

void IR::display(){
  for(codenode* i:codes){
    i->display();
  }
}

IRDriver::IRDriver(){

}

IRDriver::IRDriver(driver* myDriver):driver(myDriver),cn(NULL),bakCn(NULL),notFlag(0),cond(0){
  switch(myDriver->getNode()->nodeType){
    case SYM_COMPUNIT    :break;
    case SYM_CONSTDECL   :break;
    case SYM_VARDECL     :break;
    case SYM_CONSTDEF    :driver::addexit({DEF_codenode});                     break;
    case SYM_VARDEF      :driver::addexit({DEF_codenode});                     break;
    case SYM_FUNCDEF     :driver::addop({FUNCDEF_codenode});
                          driver::addexit({FUNCDEF_endlabel});                 break;
    case SYM_CONSTINITVAL:break;
    case SYM_INITVAL     :break;
    case SYM_FUNCFPARAMS :break;
    case SYM_PARAM       :driver::addop({PARAM_codenode});                     break;
    case SYM_BLOCK       :break;
    case SYM_BRANCH      :driver::addexit({BRANCH_codenode});                  break;
    case SYM_IF          :driver::addexit({IF_codenode});                      break;
    case SYM_ELSE        :driver::addop({ELSE_codenode});                      break;
    case SYM_WHILE       :driver::addop({WHILE_start});
                          driver::addexit({WHILE_end});                        break;
    case SYM_FOR         :break;
    case SYM_BREAK       :driver::addexit({BREAK_codenode});                   break;
    case SYM_CONTINUE    :driver::addexit({CONTINUE_codenode});                break;
    case SYM_RETURN      :driver::addexit({RETURN_codenode});                  break;
    case SYM_COND        :driver::addop({COND_set});      
                          driver::addexit({COND_codenode});                    break;
    case SYM_FUNC        :driver::addexit({FUNC_codenode});                    break;
    case SYM_CONSTEXP    :break;
    case SYM_EXP         :break;
    case SYM_BRAKET      :break;
    case SYM_ASSIGN      :driver::addexit({OP1_codenode});                     break;
    case SYM_ADD         :driver::addexit({OP2_codenode});                     break;
    case SYM_MINUS       :driver::addexit({OP2_codenode});                     break;
    case SYM_MUL         :driver::addexit({OP2_codenode});                     break;
    case SYM_DIV         :driver::addexit({OP2_codenode});                     break;
    case SYM_MOD         :driver::addexit({OP2_codenode});                     break;
    case SYM_NEGATIVE    :driver::addexit({OP1_codenode});                     break;
    case SYM_NOT         :driver::addexit({OP1_codenode});                     break;
    case SYM_AND         :driver::addop({AND_codenode});      
                          driver::addexit({AND_reset});                        break;
    case SYM_OR          :driver::addop({OR_codenode});      
                          driver::addexit({OR_reset});                         break;
    case SYM_GRATER      :driver::addexit({OP2_codenode,LOGICALOP_reset});     break;
    case SYM_LESS        :driver::addexit({OP2_codenode,LOGICALOP_reset});     break;
    case SYM_NOTLESS     :driver::addexit({OP2_codenode,LOGICALOP_reset});     break;
    case SYM_NOTGRATER   :driver::addexit({OP2_codenode,LOGICALOP_reset});     break;
    case SYM_EQUAL       :driver::addexit({OP2_codenode,LOGICALOP_reset});     break;
    case SYM_NOTEQUAL    :driver::addexit({OP2_codenode,LOGICALOP_reset});     break;
    case SYM_EMPTY       :break;
    case SYM_LIST        :break;
    case SYM_INT         :driver::addexit({VAL_codenode});                     break;
    case SYM_FLOAT       :driver::addexit({VAL_codenode});                     break;
    case SYM_TYPE_INT    :break;
    case SYM_TYPE_FLOAT  :break;
    case SYM_TYPE_VOID   :break;
    case SYM_ID          :driver::addexit({ID_codenode});                      break;
    case SYM_M           :break;
    case SYM_N           :break;
  }
}

IRDriver* IRDriver::getIRDriver(driver* myDriver){
  driver *iDriver = myDriver;
  IRDriver *iIRDriver = NULL;
  while(iIRDriver == NULL){
    iIRDriver = dynamic_cast<IRDriver*>(iDriver);
    iDriver = iDriver->myDriver;
    if(iDriver==NULL&&iIRDriver==NULL)return NULL;
  }
  return iIRDriver;
}

int DEF_codenode(driver* originDriver){
  IRDriver *myDriver = (IRDriver*)originDriver;  
  node* n = myDriver->getNode();
  if(n->children.back()->nodeType!=SYM_INITVAL)return 1;
  sym* id = mytable->find(*(n->children[0]->type_val));
  if(id->dimension==0){
    IRDriver* iDriver = IRDriver::getIRDriver(n->children.back()->children[0]->myDriver);
    codenode* tempnode = iDriver->cn;
    sym* id1 = tempnode->result;
    codenode* cn = new codenode(OP_ASSIGN,id1,id);
    myDriver->cn = cn;
    oneIR->push(cn);
  }
  return 1;
}

int FUNCDEF_codenode(driver* originDriver){
  IRDriver *myDriver = (IRDriver*)originDriver;  
  node* n = myDriver->getNode();
  sym* id = symDriver::getSymDriver(n->myDriver)->id;
  codenode* cn = new codenode(OP_FUNCTION,id);
  myDriver->cn = cn;
  oneIR->push(cn);
  return 1;
}

int FUNCDEF_endlabel(driver* originDriver){
  IRDriver *myDriver = (IRDriver*)originDriver;  
  opn* result = IR::genLabel();
  codenode* cn = new codenode(OP_LABEL,result);
  myDriver->bakCn = cn;  
  oneIR->push(cn);
  return 1;
}

int PARAM_codenode(driver* originDriver){
  IRDriver *myDriver = (IRDriver*)originDriver;  
  node* n = myDriver->getNode();
  sym* id = symDriver::getSymDriver(n->myDriver)->id;
  codenode* cn = new codenode(OP_PARAM,id);
  myDriver->cn = cn;
  oneIR->push(cn);
  return 1;
}

int FUNC_codenode(driver* originDriver){
  IRDriver *myDriver = (IRDriver*)originDriver;  
  node* n = myDriver->getNode();
  for(node* i:n->children){
    IRDriver* iDriver = IRDriver::getIRDriver(i->myDriver);
    sym* result = iDriver->cn->result;
    iDriver->cn->setValid();
    codenode* cn = new codenode(OP_ARG,result);
    iDriver->bakCn = cn;
    oneIR->push(cn);
  }
  sym* id = mytable->find(*(n->type_val));
  opn* result = IR::genTemp();
  int paramnum = n->children.size();
  if(id==NULL){
    id = new sym(*(n->type_val),
                 0,"unknown",'F',paramnum,
                 1,n->lineno,0);
  }
  codenode* cn = new codenode(OP_CALL,id,result);
  myDriver->cn = cn;
  oneIR->push(cn);
  return 1;
}

int OP2_codenode(driver* originDriver){
  IRDriver *myDriver = (IRDriver*)originDriver;  
  node* n = myDriver->getNode();
  node* n1 = n->children[0];
  node* n2 = n->children[1];
  IRDriver* iDriver1 = IRDriver::getIRDriver(n1->myDriver);
  IRDriver* iDriver2 = IRDriver::getIRDriver(n2->myDriver);
  codenode* cn1 = iDriver1->cn;
  codenode* cn2 = iDriver2->cn;
  cn1->setValid();
  cn2->setValid();
  int type;
  switch(n->nodeType){
    case SYM_ADD        :type = OP_ADD;       break;
    case SYM_MINUS      :type = OP_MINUS;     break;
    case SYM_MUL        :type = OP_MUL;       break;
    case SYM_DIV        :type = OP_DIV;       break;
    case SYM_MOD        :type = OP_MOD;       break;
    case SYM_EQUAL      :type = OP_EQUAL;     break;
    case SYM_NOTEQUAL   :type = OP_NOTEQUAL;  break;
    case SYM_GRATER     :type = OP_GRATER;    break;
    case SYM_LESS       :type = OP_LESS;      break;
    case SYM_NOTGRATER  :type = OP_NOTGRATER; break;
    case SYM_NOTLESS    :type = OP_NOTLESS;   break;
    default         :type = -1;
  }
  opn* result = IR::genTemp();
  codenode* cn = new codenode(type,cn1->result,cn2->result,result);
  myDriver->cn = cn;
  oneIR->push(cn);
  return 1;
}

int OP1_codenode(driver* originDriver){
  IRDriver *myDriver = (IRDriver*)originDriver;  
  node* n = myDriver->getNode();
  int type;
  switch(n->nodeType){
    case SYM_ASSIGN :{
                       node* n1 = n->children[0];
                       node* n2 = n->children[1];
                       codenode* cn1 = IRDriver::getIRDriver(n1->myDriver)->cn;
                       codenode* cn2 = IRDriver::getIRDriver(n2->myDriver)->cn;
                       cn1->setLval();
                       cn2->setValid();
                       codenode* cn;
                       if(cn1->op == OP_ARRAY){
                         cn = cn1;
                         cn->result = cn2->result;
                       }else{
                         cn = new codenode(OP_ASSIGN,cn2->result,cn1->result);
                       }
                       myDriver->cn = cn;
                       oneIR->push(cn); 
                     }                 
                     break;
    default         :{
                       node* n1 = n->children[0];
                       codenode* cn1 = IRDriver::getIRDriver(n1->myDriver)->cn;
                       cn1->setValid();
                       codenode* cn = new codenode(OP_NOT,cn1->result,IR::genTemp());
                       myDriver->cn = cn;
                       oneIR->push(cn);  
                     } 
                     break;
  }
  return 1;
}

int VAL_codenode(driver* originDriver){
  IRDriver *myDriver = (IRDriver*)originDriver;  
  node* n = myDriver->getNode();
  opn* result;
  if(n->nodeType==SYM_INT){
    result = new opn(n->int_val);
  }else if(n->nodeType==SYM_FLOAT){
    result = new opn(n->float_val);
  }
  codenode* cn = new codenode(OP_NULL,result);
  myDriver->cn = cn;
  return 1;
}


int ID_codenode(driver* originDriver){
  IRDriver *myDriver = (IRDriver*)originDriver;  
  node* n = myDriver->getNode();
  sym* id = mytable->find(*(n->type_val));
  opn* index = IR::genTemp();
  int dimension = 0;
  int arraySize = id->arraySize;
  for(node* i:n->children){
    if(i->nodeType == SYM_BRAKET){
      arraySize /= id->degree[dimension];
      IRDriver* iDriver = IRDriver::getIRDriver(i->myDriver);
      IRDriver* jDriver = IRDriver::getIRDriver(i->children[0]->myDriver);
      jDriver->cn->setValid();
      opn* lineSize = new opn(arraySize*4);
      if(dimension == 0){
        iDriver->cn = new codenode(OP_MUL,jDriver->cn->result,lineSize,index);
        oneIR->push(iDriver->cn);
      }else{
        opn* baseSize = IR::genTemp();
        iDriver->bakCn = new codenode(OP_MUL,jDriver->cn->result,lineSize,baseSize);
        iDriver->cn = new codenode(OP_ADD,index,baseSize,index);
        oneIR->push(iDriver->bakCn);
        oneIR->push(iDriver->cn);
      }
      dimension++;
    }
  }
  if(dimension){
    opn* result = IR::genTemp();
    codenode* cn = new codenode(OP_ARRAY,id,index,result);
    myDriver->cn = cn;
  }else{
    codenode* cn = new codenode(OP_NULL,id);
    myDriver->cn = cn; 
  }
  return 1;
}


int RETURN_codenode(driver* originDriver){
  IRDriver *myDriver = (IRDriver*)originDriver;  
  node* n = myDriver->getNode();
  if(n->children.empty()){
    codenode* cn = new codenode(OP_RETURN);
    myDriver->cn = cn;
    oneIR->push(cn);
    return 1;
  }else{
    IRDriver* iDriver = IRDriver::getIRDriver(n->children[0]->myDriver);
    iDriver->cn->setValid();
    sym* result = iDriver->cn->result;
    codenode* cn = new codenode(OP_RETURN,result);
    myDriver->cn = cn;
    oneIR->push(cn);
    return 1;
  }
}

int WHILE_start(driver* originDriver){
  IRDriver *myDriver = (IRDriver*)originDriver;  
  node* n = myDriver->getNode();
  codenode* cn = new codenode(OP_LABEL,IR::genLabel());
  myDriver->bakCn = cn;
  oneIR->push(cn);
  return 1;
}

int WHILE_end(driver* originDriver){
  IRDriver *myDriver = (IRDriver*)originDriver;  
  node* n = myDriver->getNode();
  codenode* anotherCn = new codenode(OP_GOTO,myDriver->bakCn->result);
  codenode* cn = new codenode(OP_LABEL,IR::genLabel());
  myDriver->cn = cn;
  oneIR->push(anotherCn);
  oneIR->push(cn);
  return 1;
}

int BREAK_codenode(driver* originDriver){
  IRDriver *myDriver = (IRDriver*)originDriver;  
  node* n = myDriver->getNode();
  semanticDriver *anotherDriver = semanticDriver::getSemanticDriver(n->myDriver);
  node* block = anotherDriver->block;
  IRDriver* iDriver = IRDriver::getIRDriver(block->myDriver);
  codenode* cn = new codenode(OP_GOTO,new opn(&(iDriver->cn)));
  myDriver->cn = cn;
  oneIR->push(cn);
  return 1;
}

int CONTINUE_codenode(driver* originDriver){
  IRDriver *myDriver = (IRDriver*)originDriver;  
  node* n = myDriver->getNode();
  semanticDriver *anotherDriver = semanticDriver::getSemanticDriver(n->myDriver);
  node* block = anotherDriver->block;
  IRDriver* iDriver = IRDriver::getIRDriver(block->myDriver);
  codenode* cn = new codenode(OP_GOTO,new opn(&(iDriver->bakCn)));
  myDriver->cn = cn;
  oneIR->push(cn);
  return 1;
}

int BRANCH_codenode(driver* originDriver){
  IRDriver *myDriver = (IRDriver*)originDriver;  
  node* n = myDriver->getNode();
  codenode* cn = new codenode(OP_LABEL,IR::genLabel());
  myDriver->cn = cn;
  if(n->children.size()>1){
    IRDriver *iDriver = IRDriver::getIRDriver(n->children.back()->myDriver);
    myDriver->bakCn = new codenode(OP_NULL,new opn(&(iDriver->cn)));
  }else{
    myDriver->bakCn = cn;
  }
  oneIR->push(cn);
  return 1;
}

int IF_codenode(driver* originDriver){
  IRDriver *myDriver = (IRDriver*)originDriver;  
  node* n = myDriver->getNode();
  IRDriver *parentDriver = IRDriver::getIRDriver(n->parent->myDriver);
  codenode* cn = new codenode(OP_NULL,new opn(&(parentDriver->bakCn)));
  myDriver->cn = cn;
  return 1;
}

int ELSE_codenode(driver* originDriver){
  IRDriver *myDriver = (IRDriver*)originDriver;  
  node* n = myDriver->getNode();
  IRDriver *parentDriver = IRDriver::getIRDriver(n->parent->myDriver);
  codenode* bakCn = new codenode(OP_GOTO,new opn(&(parentDriver->cn)));
  codenode* cn = new codenode(OP_LABEL,IR::genLabel());
  myDriver->cn = cn;
  myDriver->bakCn = bakCn;
  oneIR->push(bakCn);
  oneIR->push(cn);
  return 1;
}

void setNotFlag(node *n){
  for(node* i:n->children){
    IRDriver *iDriver = IRDriver::getIRDriver(i->myDriver);
    iDriver->notFlag = 1 - iDriver->notFlag;
  }
}

void setCond(node* n){
  for(node* i:n->children){
    IRDriver *iDriver = IRDriver::getIRDriver(i->myDriver);
    iDriver->cond = 1;
  }
}

void setGap(node* n){
  for(node* i:n->children){
    IRDriver *iDriver = IRDriver::getIRDriver(i->myDriver);
    iDriver->gap = 1;
  }
}

int notOP(int originOP){
  switch(originOP){
    case OP_EQUAL      :return OP_NOTEQUAL   ;
    case OP_NOTEQUAL   :return OP_EQUAL      ;
    case OP_GRATER     :return OP_NOTGRATER  ;
    case OP_NOTGRATER  :return OP_GRATER     ;
    case OP_LESS       :return OP_NOTLESS    ;
    case OP_NOTLESS    :return OP_LESS       ;
    default            :return originOP      ;
  }
}

int COND_codenode(driver* originDriver){
  IRDriver *myDriver = (IRDriver*)originDriver;  
  node* n = myDriver->getNode();
  IRDriver *parentDriver = IRDriver::getIRDriver(n->parent->myDriver);
  if(n->children[0]->nodeType != SYM_OR){
    codenode* cn = new codenode(OP_NULL,new opn(&(parentDriver->cn)));
    myDriver->cn = cn;
  }else{
    IRDriver *lastDriver = IRDriver::getIRDriver(n->children[0]->children[1]->myDriver);
    lastDriver->cn->setCond(new opn(&(parentDriver->cn)));
    codenode* cn = new codenode(OP_LABEL,IR::genLabel());
    codenode* bakCn = new codenode(OP_NULL,new opn(&(parentDriver->cn)));
    myDriver->cn = cn;
    oneIR->push(cn);
  }
  return 1;
}

int COND_set(driver* originDriver){
  IRDriver *myDriver = (IRDriver*)originDriver;  
  node* n = myDriver->getNode();
  if(n->children[0]->nodeType == SYM_OR){
    IRDriver *firstDriver = IRDriver::getIRDriver(n->children[0]->children[0]->myDriver);
    firstDriver->gap = 1;
  }
  setCond(n);
  setNotFlag(n);
  return 1;
}

int LOGICALOP_reset(driver* originDriver){
  IRDriver *myDriver = (IRDriver*)originDriver;  
  node* n = myDriver->getNode();
  IRDriver *parentDriver = IRDriver::getIRDriver(n->parent->myDriver);
  if(myDriver->gap){
    myDriver->notFlag = 1 - myDriver->notFlag;
  }
  if(myDriver->cond)myDriver->cn->setCond(new opn(&(parentDriver->cn)));
  if(myDriver->notFlag)myDriver->cn->op = notOP(myDriver->cn->op);
  return 1;
}

int AND_codenode(driver* originDriver){
  IRDriver *myDriver = (IRDriver*)originDriver;  
  node* n = myDriver->getNode();
  IRDriver *parentDriver = IRDriver::getIRDriver(n->parent->myDriver);
  if(myDriver->cond)setCond(n);
  if(myDriver->notFlag){
    setNotFlag(n);
    myDriver->cn = new codenode(OP_NULL,new opn(&(parentDriver->cn)));
  }else{
    printf("%d && not in cond",n->lineno);
  }
  return 1;
}

int OR_codenode(driver* originDriver){
  IRDriver *myDriver = (IRDriver*)originDriver;  
  node* n = myDriver->getNode();
  if(myDriver->cond)setCond(n);
  if(myDriver->gap)setGap(n);
  if(myDriver->notFlag){
    setNotFlag(n);
    IRDriver *parentDriver = IRDriver::getIRDriver(n->parent->myDriver);
    myDriver->cn = new codenode(OP_NULL,new opn(&(parentDriver->cn)));
  }else{
    printf("%d && not in cond",n->lineno);
  }
  return 1;
}

int AND_reset(driver* originDriver){
  IRDriver *myDriver = (IRDriver*)originDriver;  
  node* n = myDriver->getNode();
  IRDriver *parentDriver = IRDriver::getIRDriver(n->parent->myDriver);
  if(myDriver->notFlag){
    setNotFlag(n);
  }
  if(myDriver->gap){
    codenode* cn1 = new codenode(OP_GOTO,new opn(&(parentDriver->cn))); 
    codenode* cn2 = new codenode(OP_LABEL,IR::genLabel());
    myDriver->cn = cn2;
    oneIR->push(cn1);
    oneIR->push(cn2);
  }else{
    codenode* cn = new codenode(OP_NULL,new opn(&(parentDriver->cn)));
    myDriver->cn = cn;
  }
  return 1;
}

int OR_reset(driver* originDriver){
  IRDriver *myDriver = (IRDriver*)originDriver;  
  node* n = myDriver->getNode();
  if(myDriver->notFlag){
    
  }
  return 1;
}

//array initialize
//cond jump

